﻿@page "/FeeWindow"
@using SelfService.Model.Interface
@using SelfService.Model.Models
@using SelfService.Model.ViewModels
@using System.Net
@using Quartz.Util
@using SelfService.Model.Request
@using SelfService.ViewModel.SysMedicalProjectVMs
@using System.Diagnostics
@using System.Text.RegularExpressions
@inherits BasePage
@inject SwalService SwalService
@attribute [ActionDescription("门诊收费", "NameMaster.Controllers,FeeWindow")]

<div class="main">
    <div class="item">
        <div class="item-label">收费项目</div>
        <div class="item-content">
            <RadioList TValue="string" @bind-Value="@_projectId" Items="@_projectItems" IsButton="true" OnSelectedChanged="@OnProjectSelectedChanged"></RadioList>
        </div>
    </div>
    <div class="item">
        <div class="item-label">项目数量</div>
        <div class="item-content">
            <div class="info">
                <BootstrapInputNumber 
                    @bind-Value="@Qty" 
                    IsSelectAllTextOnFocus="true"
                    Min="1"
                    TValue="int"
                    IsDisabled="IsControlQty"/>
            </div>
        </div>
    </div>
    <div class="item">
        <div class="item-label">选择用户</div>
        <div class="item-content">
            <div class="search-bar">
                <Search IsAutoFocus="true"
                        @bind-Value="@_search"
                        OnSearch="@Search"
                        OnClear="@Clear"
                        SearchButtonText="查询"
                        ShowClearButton="true"
                        SearchButtonLoadingIcon="fa-fw fa-spin fa-solid fa-spinner"
                        PlaceHolder="请输入身份证号码或者扫描二维码"
                        IsSelectAllTextOnFocus="true"/>
            </div>
            <div class="search-btn">
                <Button Color="Color.Secondary" IsAsync="true" OnClick="@ReadCard">读卡</Button>
            </div>
        </div>
    </div>
    @if (_patient != null)
    {
        <div class="item">
            <div class="item-label">用户信息</div>
            <div class="item-content">
                <div class="info">
                    <div class="info-label">姓名:</div>
                    <div class="info-content">@_patient.Name</div>
                </div>
                <div class="info">
                    <div class="info-label">年龄:</div>
                    <div class="info-content">@_patient.Age</div>
                </div>
                <div class="info">
                    <div class="info-label">性别:</div>
                    <div class="info-content">@_patient.Sex</div>
                </div>
                <div class="info">
                    <div class="info-label">储值卡余额:</div>
                    <div class="info-content">@_patient.Balance<span>元</span></div>
                </div>
            </div>
        </div>
        @* <div class="item"> *@
        @*     <div class="item-label">支付方式</div> *@
        @*     <div class="item-content"> *@
        @*         <RadioList @bind-Value="@_payMethod" Items="PayMethods" IsButton="true"></RadioList> *@
        @*     </div> *@
        @* </div> *@
    }
</div>
<div class="order-footer">
    <div class="footer-content">
        <div>合计:</div>
        <span class="sep">￥</span>
        <span class="amount">@Amount.ToString("0.00")</span>
        <Button Class="bg-red" IsDisabled="_patient == null" OnClick="@SubmitPay">确认支付</Button>
    </div>
</div>
@if (_showPayPage)
{
    <div class="pay-box">
        <div class="pay-content">
            <Circle Value="@_circleValue">
                <div class="circle-content">
                    <div class="time">@_time</div>
                </div>
            </Circle>
            <div class="tip">@_tip</div>
            @if (_showAuthCode)
            {
                <div>
                    <Search @bind-Value="@_authCode"
                            IsAutoFocus="true"
                            OnSearch="@StartPay"
                            OnClear="Clear"
                            SearchButtonText="收款"
                            ShowClearButton="true"
                            NoDataTip="加载中...."
                            PlaceHolder="请扫描用户付款码"
                            SearchButtonIcon="fas fa-hand-holding-dollar"
                            IsSelectAllTextOnFocus="true"/>
                </div>
            }
            @if (_showClose)
            {
                <div><Button Color="Color.Secondary" OnClick="@CloseToast">关闭</Button></div>
            }
        </div>
    </div>
}

@code {
    protected override async Task OnInitializedAsync()
    {
        await GetProjectList();
        await GetPayMethod();
        await base.OnInitializedAsync();
    }

    private SelectedItem _payMethod;
    private List<SelectedItem> _projectItems;
    private List<SysMedicalProjectView> _projectViewsList = new();
    private SysMedicalProject _project;
    private string _projectId;
    private SysPatient _patient = null;
    private string _search = "";
    private int Qty { get; set; } = 1;
    private decimal Amount => _project == null ? 0 : decimal.Round(Qty * _project.Price, 2);
    private string _tip = "订单创建中";
    private string _authCode = "";
    private bool _showPayPage;
    private bool _showAuthCode;
    private bool _showClose;
    private int _circleValue = 100;
    private int _time = 0;

    /// <summary>
    /// 获取项目列表
    /// </summary>
    /// <returns></returns>
    private async Task GetProjectList()
    {
        var result = await WtmBlazor.Api.CallAPI<WtmApiResult<SysMedicalProjectView>>("/api/SysMedicalProject/Search", HttpMethodEnum.POST, new { });
        if (result.StatusCode == HttpStatusCode.OK && result.Data.Code == 200)
        {
            _projectItems = new List<SelectedItem>();
            foreach (var element in result.Data.Data)
            {
                var item = new SelectedItem()
                {
                    Text = element.Name,
                    Value = element.ID.ToString(),
                    IsDisabled = element.IsDisable
                };
                _projectItems.Add(item);
            }
            //保存项目列表, 用于计算金额
            _projectViewsList = result.Data.Data;
            //从缓存读取上一次的收费项目
            var id = await GetLocalStorage<string>(nameof(_projectId));
            //设置当前选择收费项目
            var project = _projectViewsList.FirstOrDefault(e => e.ID.ToString() == id);
            if (project != null)
            {
                _project = project;
                _projectId = id;
            }
        }
    }

    private List<SelectedItem> PayMethods { get; set; }

    /// <summary>
    /// 获取支付方式
    /// </summary>
    /// <returns></returns>
    private async Task GetPayMethod()
    {
        var result = await WtmBlazor.Api.CallAPI<WtmApiResult<SysPayType>>("/api/SysPayType/Search", HttpMethodEnum.POST, new { });
        if (result.StatusCode == HttpStatusCode.OK && result.Data.Code == 200)
        {
            PayMethods = new List<SelectedItem>();
            foreach (var element in result.Data.Data)
            {
                var item = new SelectedItem()
                {
                    Text = element.Name,
                    Value = element.ID.ToString(),
                };
                PayMethods.Add(item);
            }
        }
    }

    /// <summary>
    /// 收费项目改变事件
    /// </summary>
    /// <param name="items"></param>
    /// <param name="value"></param>
    /// <returns></returns>
    private async Task OnProjectSelectedChanged(IEnumerable<SelectedItem> items, string value)
    {
        var project = _projectViewsList.FirstOrDefault(e => e.ID.ToString() == value);
        if (project != null)
        {
            _project = project;
            _projectId = value;
            await SetLocalStorage(nameof(this._projectId), value);
        }
    }

    /// <summary>
    /// 是否控制数量
    /// </summary>
    private bool IsControlQty => _project?.IsControlQty ?? true;

    /// <summary>
    /// 搜索
    /// </summary>
    /// <param name="idCardNo">身份证号码</param>
    /// <returns></returns>
    private async Task Search(string idCardNo)
    {
        if (idCardNo.Trim().Length == 0) return;
        var search = new SysPatientSearcher();
        search.IdCardNo = idCardNo.Trim();
        await GetPatient(search);
    }

    /// <summary>
    /// 清空
    /// </summary>
    /// <param name="idCardNo">身份证号码</param>
    /// <returns></returns>
    private Task Clear(string idCardNo)
    {
        this.CloseToast();
        return Task.CompletedTask;
    }

    /// <summary>
    /// 查询患者信息
    /// </summary>
    /// <param name="search"></param>
    /// <returns></returns>
    private async Task GetPatient(SysPatientSearcher search)
    {
        var result = await WtmBlazor.Api.CallAPI<Result<SysPatient>>("/api/SysPatient/GetUser", HttpMethodEnum.POST, search);
        if (result.Data is { Code: 200, Data: { } })
        {
            this._patient = result.Data.Data;
            this._payMethod ??= this.PayMethods.FirstOrDefault();
            await InvokeAsync(StateHasChanged);
            return;
        }
        var op = new SwalOption()
        {
            Category = SwalCategory.Error,
            Title = $"",
            Content = "没有找到用户的建档信息, 如果用户携带身份证或者社保卡可以自助建档",
            ShowClose = true
        };
        await SwalService.Show(op);
    }

    /// <summary>
    /// 读卡
    /// </summary>
    /// <returns></returns>
    private async Task ReadCard()
    {
        var result = await JSRuntime.InvokeAsync<Result<SysPatient>>("httpRequest", "http://127.0.0.1:6161/device?action=read");
        if (result != null)
        {
            if (result.Code == 200)
            {
                var patient = result.Data;
                if (!string.IsNullOrWhiteSpace(patient.IdCardNo))
                {
                    var search = new SysPatientSearcher();
                    search.IdCardNo = patient.IdCardNo;
                    _search = patient.IdCardNo;
                    await GetPatient(search);
                }
                else if (!string.IsNullOrWhiteSpace(patient.CardNo))
                {
                    var search = new SysPatientSearcher();
                    search.CardNo = patient.CardNo;
                    _search = patient.CardNo;
                    await GetPatient(search);
                }
                else
                {
                    await WtmBlazor.Toast.Error("错误", "读卡失败");
                }
            }
            else
            {
                await WtmBlazor.Toast.Error("错误", result.Message);
            }
        }
        else
        {
            await WtmBlazor.Toast.Error("错误", "读卡失败");
        }
    }

    private SysPrescription _prescription = null;
    
    /// <summary>
    /// 提交订单
    /// </summary>
    /// <returns></returns>
    private async Task SubmitPay()
    {
        _showPayPage = true;
        _tip = "正在生成处方..";
        ShowTimer(60);
        var postData = new CreateTreamentRequest()
        {
            PatientId = this._patient.ID,
            ProjectId = this._project.ID,
            Qty = this.Qty
        };
        var prescription = await this.CreatePrescription(postData);
        if (prescription != null)
        {
            ShowTimer(60);
            this._prescription = prescription;
            _tip = "请扫描用户付款码";
            _showAuthCode = true;
            _showClose = true;
        }
    }
    
    /// <summary>
    /// 关闭弹出框
    /// </summary>
    /// <returns></returns>
    private Task CloseToast()
    {
        _showAuthCode = false;
        _showClose = false;
        _showPayPage = false;
        _patient = null;
        _tip = "";
        _search = "";
        _prescription = null;
        _authCode = "";
        return Task.CompletedTask;
    }

    /// <summary>
    /// 开始订单
    /// </summary>
    /// <returns></returns>
    private async Task StartPay(string authCode)
    {
        if (!_authCode.IsNullOrWhiteSpace())
        {
            var wechat = @"^1[0-5]\d{16}$";
            var alipay = @"^(2[5-9]|30)\d{14,22}$";
            _payMethod = null;
            if (Regex.IsMatch(_authCode, wechat)) _payMethod = PayMethods.FirstOrDefault(e => e.Text == "微信");
            if (Regex.IsMatch(_authCode, alipay)) _payMethod = PayMethods.FirstOrDefault(e => e.Text == "支付宝");
            if (_payMethod == null)
            {
                await WtmBlazor.Toast.Error("错误", "不可识别的付款码, 请重新扫码");
                _authCode = "";
                StateHasChanged();
                return;
            }
            _ = Task.Run(async () =>
            {
                ShowTimer(60);
                _tip = $"正在创建[{_payMethod.Text}]订单";
                _showAuthCode = false;
                _showClose = false;
                await InvokeAsync(StateHasChanged);
                //处理支付
                var pay = new SysPay();
                pay.PatientId = _patient.ID;
                pay.PayStatus = PayStatusEnum.待支付;
                pay.AuthCode = _authCode;
                pay.Amount = Amount;
                pay.OutOrderNo = Guid.NewGuid().ToString("N");
                pay.CreateTime = DateTime.Now;
                pay.UpdateTime = DateTime.Now;
                pay.Use = PayUseEnum.缴费;
                pay.CreateBy = this.UserInfo.ITCode;
                pay.UpdateBy = this.UserInfo.ITCode;
                pay.PayTypeId = Guid.Parse(_payMethod.Value);
                pay.ID = Guid.NewGuid();
                var result = await this.CreatePayOrder(pay);
                if (result != null)
                {
                    ShowTimer(60);
                    pay = result;
                    await CheckResult(pay.ID.ToString());
                }
            });
        }
        else
        {
            await WtmBlazor.Toast.Error("错误", "付款码不能为空");
        }
    }

    /// <summary>
    /// 创建处方
    /// </summary>
    /// <returns></returns>
    private async Task<SysPrescription> CreatePrescription(CreateTreamentRequest postData)
    {
        var result = await WtmBlazor.Api.CallAPI<Result<SysPrescription>>("/api/SysPrescription/CreatePrescription", HttpMethodEnum.POST, postData);
        if (result != null)
        {
            if (result.Data.Code == 200)
            {
                return result.Data.Data;
            }
            else
            {
                _tip = $"处方创建失败, {result.Data.Message}";
                _showClose = true;
                StateHasChanged();
                return null;
            }
        }
        else
        {
            _tip = "处方创建失败, 网络故障, 请稍后重试!";
            _showClose = true;
            StateHasChanged();
            return null;
        }
    }
    
    /// <summary>
    /// 创建支付订单
    /// </summary>
    /// <returns></returns>
    private async Task<SysPay> CreatePayOrder(SysPay payInfo)
    {
        var result = await WtmBlazor.Api.CallAPI<Result<SysPay>>("/api/SysPay/MicroPay", HttpMethodEnum.POST, payInfo);
        if (result != null)
        {
            if (result.Data.Code == 200)
            {
                return result.Data.Data;
            }
            else
            {
                _tip = "支付失败";
                _showClose = true;
                StateHasChanged();
                return null;
            }
        }
        else
        {
            _tip = "支付失败, 网络故障, 请稍后重试";
            _showClose = true;
            StateHasChanged();
            return null;
        }
    }
    
    /// <summary>
    /// 检查支付状态
    /// </summary>
    /// <returns></returns>
    private async Task CheckResult(string id)
    {
        _time = 60;
        _tip = "等待用户支付...";
        _showClose = true;
        ShowTimer(60);
        await InvokeAsync(StateHasChanged);
        for (int i = 0; i < _time; i++)
        {
            var sw = new Stopwatch();
            sw.Start();
            var result = await WtmBlazor.Api.CallAPI<Result<SysPay>>($"/api/SysPay/GetPayResult?id={id}");
            if (result != null && result.Data.Code == 200 && result.Data.Data.PayStatus == PayStatusEnum.支付成功)
            {
                _tip = "支付成功, 等待HIS处理中..";
                ShowTimer(60);
                await InvokeAsync(StateHasChanged);
                var request = new PayOrderRequest();
                request.OrderId = _prescription.ID;
                request.PayId = Guid.Parse(id);
                var prescription = await PayOrder(request);
                if (prescription != null)
                {
                    ShowTimer(60);
                    _tip = "缴费成功!";
                    _showClose = true;
                    await InvokeAsync(StateHasChanged);
                }
                break;
            }
            sw.Stop();
            var t = (int)(1000 - sw.Elapsed.TotalMilliseconds);
            if (t > 0) await Task.Delay(t);
        }
    }
    
    /// <summary>
    /// 缴费
    /// </summary>
    /// <returns></returns>
    private async Task<SysPrescription> PayOrder(PayOrderRequest request)
    {
        var result = await WtmBlazor.Api.CallAPI<Result<SysPrescription>>("/api/SysPrescription/PayOrder", HttpMethodEnum.POST, request);
        if (result != null)
        {
            if (result.Data.Code == 200)
            {
                return result.Data.Data;
            }
            else
            {
                _tip = $"缴费失败, {result.Data.Message}";
                _showClose = true;
                await InvokeAsync(StateHasChanged);
            }
        }
        else
        {
            _tip = "缴费失败, 网络故障, 请稍后重试";
            _showClose = true;
            await InvokeAsync(StateHasChanged);
        }
        return null;
    }


    private bool _timerRun = false;
    private int _second = 0;
    private void ShowTimer(int second)
    {
        _time = second;
        _second = second;
        if (_timerRun) return;
        _timerRun = true;
        Task.Run(async () =>
        {
            while (_time > 0)
            {
                _time--;
                _circleValue = (int)((double)_time / _second * 100);
                await InvokeAsync(StateHasChanged);
                await Task.Delay(1000);
            }
            _timerRun = false;
            await CloseToast();
            await InvokeAsync(StateHasChanged);
        });
    }
}